import os
import subprocess
import winreg
import shutil
import ctypes
from typing import List, Dict, Any
import json
from tqdm import tqdm
from .base import Tool
import base64

TOOL = Tool(
    name="windows",
    description="Windows系统管理工具",
    parameters={
        "action": {
            "type": "string",
            "description": "操作类型(copy_file/move_file/compress/decompress/get_sys_info/reg_query)",
            "required": True
        },
        "params": {
            "type": "string",
            "description": "操作参数的JSON字符串",
            "required": True
        }
    },
    example='''<windows>
<action>copy_file</action>
<params>{"source": "test.txt", "destination": "backup/test.txt"}</params>
</windows>'''
)

def is_admin():
    """检查是否有管理员权限"""
    try:
        return ctypes.windll.shell32.IsUserAnAdmin()
    except:
        return False

def ensure_dir(path):
    """确保目录存在"""
    directory = os.path.dirname(os.path.abspath(path))
    if not os.path.exists(directory):
        os.makedirs(directory)

def copy_file(params: Dict[str, str]) -> str:
    """复制文件"""
    try:
        source = params.get('source')
        destination = params.get('destination')
        if not (source and destination):
            return "错误: 需要提供源文件和目标路径"
            
        # 确保源文件存在
        if not os.path.exists(source):
            return f"错误: 源文件不存在: {source}"
            
        # 创建目标目录
        ensure_dir(destination)
        
        # 复制文件
        shutil.copy2(source, destination)
        return f"文件已复制: {source} -> {destination}"
    except Exception as e:
        return f"复制文件时出错: {str(e)}"

def move_file(params: Dict[str, str]) -> str:
    """移动文件"""
    try:
        source = params.get('source')
        destination = params.get('destination')
        if not (source and destination):
            return "错误: 需要提供源文件和目标路径"
            
        # 确保源文件存在
        if not os.path.exists(source):
            return f"错误: 源文件不存在: {source}"
            
        # 创建目标目录
        ensure_dir(destination)
        
        # 移动文件
        shutil.move(source, destination)
        return f"文件已移动: {source} -> {destination}"
    except Exception as e:
        return f"移动文件时出错: {str(e)}"

def compress_files(params: Dict[str, Any]) -> str:
    """压缩文件"""
    try:
        source = params.get('source')
        output = params.get('output')
        if not (source and output):
            return "错误: 需要提供源文件/目录和输出路径"
            
        # 确保源文件存在
        if not os.path.exists(source):
            return f"错误: 源文件/目录不存在: {source}"
            
        # 确保输出文件有zip后缀
        if not output.endswith('.zip'):
            output += '.zip'
            
        # 获取绝对路径
        source = os.path.abspath(source)
        output = os.path.abspath(output)
        
        # 创建输出目录
        ensure_dir(output)
        
        # 压缩文件/目录
        base_name = os.path.splitext(output)[0]
        root_dir = os.path.dirname(source)
        base_dir = os.path.basename(source)
        
        shutil.make_archive(base_name, 'zip', root_dir, base_dir)
        return f"压缩完成: {output}"
    except Exception as e:
        return f"压缩文件时出错: {str(e)}"

def decompress_file(params: Dict[str, str]) -> str:
    """解压文件"""
    try:
        source = params.get('source')
        destination = params.get('destination', '.')
        if not source:
            return "错误: 需要提供源文件路径"
            
        # 确保源文件存在
        if not os.path.exists(source):
            return f"错误: 源文件不存在: {source}"
            
        # 创建解压目录
        os.makedirs(destination, exist_ok=True)
        
        # 解压文件
        shutil.unpack_archive(source, destination)
        return f"解压完成: {source} -> {destination}"
    except Exception as e:
        return f"解压文件时出错: {str(e)}"

def get_sys_info() -> str:
    """获取系统信息"""
    try:
        info = {}
        
        # 获取系统信息
        sys_info = subprocess.check_output('systeminfo', encoding='gbk')
        info['system'] = sys_info.split('\n')[:20]  # 只保留前20行
        
        # 获取网络配置
        net_info = subprocess.check_output('ipconfig /all', encoding='gbk')
        info['network'] = net_info.split('\n')[:20]  # 只保留前20行
        
        # 获取磁盘信息
        disk_info = subprocess.check_output('wmic logicaldisk get caption,description,freespace,size', encoding='gbk')
        info['disk'] = disk_info.split('\n')
        
        return json.dumps(info, ensure_ascii=False, indent=2)
    except Exception as e:
        return f"获取系统信息时出错: {str(e)}"

def reg_query(params: Dict[str, str]) -> str:
    """查询注册表"""
    try:
        key_path = params.get('key_path')
        value_name = params.get('value_name')
        if not key_path:
            return "错误: 需要提供注册表路径"
            
        # 打开注册表键
        root_key = winreg.HKEY_LOCAL_MACHINE
        if key_path.startswith('HKEY_CURRENT_USER'):
            root_key = winreg.HKEY_CURRENT_USER
            key_path = key_path[18:]
        elif key_path.startswith('HKEY_LOCAL_MACHINE'):
            key_path = key_path[19:]
            
        key = winreg.OpenKey(root_key, key_path, 0, winreg.KEY_READ)
        
        # 处理结果
        def handle_value(value):
            """处理注册表值"""
            if isinstance(value, bytes):
                return base64.b64encode(value).decode('utf-8')
            return value
        
        # 获取结果
        if value_name:
            value, type_id = winreg.QueryValueEx(key, value_name)
            result = {
                'name': value_name,
                'value': handle_value(value),
                'type': type_id
            }
        else:
            result = {}
            try:
                i = 0
                while True:
                    name, value, type_id = winreg.EnumValue(key, i)
                    result[name] = {
                        'value': handle_value(value),
                        'type': type_id
                    }
                    i += 1
            except WindowsError:
                pass
                
        winreg.CloseKey(key)
        return json.dumps(result, ensure_ascii=False, indent=2)
    except Exception as e:
        return f"查询注册表时出错: {str(e)}"

def execute(params: dict) -> str:
    """执行windows工具"""
    try:
        action = params.get("action", "")
        if not action:
            return "错误：未提供操作类型"
            
        result = perform_action(action)
        return result
        
    except Exception as e:
        return f"执行Windows操作失败: {str(e)}"